package com.hy.video.monitor.repository;

import com.hy.video.monitor.domain.QRole;
import com.hy.video.monitor.domain.Role;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.StringExpression;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer;
import org.springframework.data.querydsl.binding.QuerydslBindings;
import org.springframework.stereotype.Repository;
import java.util.Optional;
import java.util.Set;
/**
 * JPA:参考：https://blog.csdn.net/xfx_1994/article/details/104921234
 * JpaRepository支持接口规范方法名查询。
 * 意思是如果在接口中定义的查询方法符合它的命名规则，就可以不用写实现，目前支持的关键字如下。
 * 使用时自定义接口继承JpaRepository，传入泛型，第一个参数为要操作的实体类，第二个参数为该实体类的主键类型
 *
 * 1、JPA的@NamedQueries
 * (1)1：在实体类上使用@NamedQuery
 *      @NamedQuery(name = "Spu.findByRootCategoryId",query = "select s from Spu s where s.rootCategoryId >= ?1")
 * (2)在自己实现的DAO的Repository接口里面定义一个同名的方法，示例如下：
 *      public List<Spu> findByRootCategoryId(Long rootCategoryId);
 * (3)然后Spring会先找是否有同名的NamedQuery，如果有，那么就不会按照接口定义的方法来解析。
 * 2. 使用@Query
 * 在方法上标注@Query来指定本地查询
 * 参数nativeQuery默认为false，nativeQuery=false时，value参数写的是JPQL，JPQL是用来操作model对象的
 *      @Query(value="select s from Spu s where s.title like %?1" )
 *      public List<Spu> findByTitle(String title);
 *      nativeQuery=true时，value参数写的是原生sql
 *      @Query(value="select * from spu s where s.title like %?1",nativeQuery=true )
 *      public List<Spu> findByTitle(String title);
 * 3.使用@Param命名化参数
 *     @Query(value = "select s from Spu s where s.title in (:titles)")
 *     List<Spu> findByTitle(@Param("titles") List<String> titles);
 */
@Repository
public interface RoleRepo extends JpaRepository<Role, Long>, QuerydslPredicateExecutor<Role>, QuerydslBinderCustomizer<QRole> {
//public interface RoleRepo extends JpaRepository<Role, Long>, QuerydslPredicateExecutor<Role> {

//    Set<Role> findByAuthorityIn(Set<String> authority);
//
//    Optional<Role> findOptionalByAuthority(String authority);
    @Override
    Page<Role> findAll(Predicate predicate, Pageable pageable);

    Optional<Role> findOptionalByRoleName(String roleName);

    Set<Role> findByIdIn(Set<Long> ids);

    @Query("select count(r) from Role r inner join r.users ru where r.id = ?1")
    long countByAssigned(Long id);

    long countByRoleNameIgnoreCase(String roleName);

    long countByRoleNameIgnoreCaseAndIdNot(String roleName, Long Id);

    @Override
    default void customize(QuerydslBindings bindings, QRole root) {
        bindings.bind(root.roleName).first(StringExpression::containsIgnoreCase);
        bindings.bind(root.displayName).first(StringExpression::containsIgnoreCase);
    }
}
